home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
201-225
/
225
/
mymenu
/
mon.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-13
|
6KB
|
191 lines
/* Copyright ) Darin Johnson, 1989 */
/* This file has routines to allow us to 'monitor' an Intuition port */
/* What happens, is that we create a port, myPort, and set things up */
/* so that GetMsg works normally for myPort, and the original port, */
/* winPort. However, PutMsg to myPort will put the new message */
/* on winPort, and vice-versa. Basically, the heads of both message */
/* lists are normal, but the two tails have been swapped. Since */
/* GetMsg uses the head of the list, it acts normally. PutMsg uses */
/* the tail of the list, so it acts differently. (the sigBit and */
/* sigTasks have also been swapped) */
/* What this means, is that anything PutMsg'ed to the winPort, will */
/* signal us, and we can GetMsg it. When we are finished looking at */
/* that message, we can give it to winPort by PutMsg'ing to myPort. */
#include <exec/ports.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <intuition/intuitionbase.h>
#include <devices/inputevent.h>
#include <functions.h>
#include "mymenu.h"
#ifdef DO_WB
extern struct MsgPort *wb_reply_port;
extern int wb_cnt;
#endif
static struct MsgPort *winPort;
static struct List *winMsgList;
static LONG winSignal, our_signal;
static LONG winMask;
static BYTE orig_pri;
/* our port */
static struct MsgPort myPort =
{
{NULL, NULL, NT_MSGPORT, 0, NULL},
PA_SIGNAL,
0,
NULL,
{NULL, NULL, NULL, NT_MESSAGE, 0}
};
static struct List *myMsgList = &(myPort.mp_MsgList);
/* fiddle with the two ports, setting things up */
make_MsgPort()
{
Forbid();
/* get the info we need */
winPort = MM->WBWindow->UserPort;
winMsgList = &(winPort->mp_MsgList);
winSignal = winPort->mp_SigBit;
winMask = 1L << winSignal;
/* setup our port */
myPort.mp_SigBit = winSignal;
myPort.mp_SigTask = winPort->mp_SigTask;
/* flip things around */
winPort->mp_SigTask = MM->handler_task;
myMsgList->lh_Head = (struct Node *)&(winMsgList->lh_Tail);
myMsgList->lh_TailPred = winMsgList->lh_TailPred;
winMsgList->lh_TailPred = (struct Node *)&(myMsgList->lh_Head);
myMsgList->lh_TailPred->ln_Succ = (struct Node *)&(myMsgList->lh_Tail);
Permit();
/* prevent deadlocks */
orig_pri = SetTaskPri(MM->handler_task,
myPort.mp_SigTask->tc_Node.ln_Pri+1);
}
/* Restore things the way they were before make_MsgPort() */
/* Note that we don't refer to winPort. This is because we */
/* may have had someone else 'monitor' this port (such as MonIDCMP) */
/* besides us. */
del_MsgPort() {
struct Message *tmpMsg;
struct MsgPort *tmpPort;
Forbid();
/* clean out our list */
while ((tmpMsg = GetMsg(&myPort)) != NULL) PutMsg(&myPort, tmpMsg);
/* find MsgPort that myMsgList->lh_Head belongs to */
/* (the port we've been PutMsg'ing to) */
tmpPort = (struct MsgPort *) (
(UBYTE*) &myPort - (UBYTE*) &(myPort.mp_MsgList.lh_Tail)
+ (UBYTE*)myMsgList->lh_Head);
/* restore things */
myMsgList->lh_Head->ln_Pred = myMsgList->lh_TailPred;
myMsgList->lh_TailPred->ln_Succ = myMsgList->lh_Head;
tmpPort->mp_SigTask = myPort.mp_SigTask;
Permit();
SetTaskPri(MM->handler_task, orig_pri);
}
/* do all appropriate initialization of monitor */
BOOL setup_mon()
{
make_MsgPort();
/* we need to allocate the same signal, so that it doesn't get
allocated to something else, messing us up */
our_signal = AllocSignal(winSignal);
if (our_signal != winSignal) {
finish_mon();
return FALSE;
}
return TRUE;
}
/* clean up everything */
finish_mon() {
del_MsgPort();
FreeSignal(our_signal);
}
/* See if we handle this event. If so, return ext_MenuItem structure */
struct ext_MenuItem *
match_item(Class, Code)
ULONG Class;
USHORT Code;
{
register struct ext_MenuItem *tmp;
if (Class != MENUPICK || Code == MENUNULL)
return NULL;
for (tmp = MM->item_list; tmp; tmp=tmp->next_item)
if (tmp->id == Code)
return tmp;
return NULL;
}
/* The actual monitor. Just keep waiting for messages, and acting on them */
/* Note that if we don't use a certain IDCMP message, we PutMsg it to get */
/* it back to the window it was meant for. */
monitor()
{
register struct IntuiMessage *msg;
register void *item;
register ULONG mask, wb_mask;
#ifdef DO_WB
winMask |= (wb_mask = (1L << wb_reply_port->mp_SigBit));
#endif
winMask |= SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D;
while (TRUE) {
mask = Wait(winMask);
if (mask & SIGBREAKF_CTRL_C) {
/* caught ^C, time to close up */
break;
}
if (mask & SIGBREAKF_CTRL_D) {
/* reparse menus */
del_menu_strip();
Signal(MM->parent_task, (1 << MM->parent_sig));
Wait(SIGBREAKF_CTRL_D);
add_menu_strip();
continue;
}
#ifdef DO_WB
if (mask & wb_mask) {
/* caught a reply from a WorkBench program exitting */
register struct Message *wb_msg;
while ((wb_msg = GetMsg(wb_reply_port)) != NULL) {
wbfree(wb_msg);
wb_cnt = (wb_cnt>0 ? (wb_cnt-1) : 0);
}
continue;
}
#endif
/* if we got here, we have an IDCMP message */
while ((msg = (struct IntuiMessage *)GetMsg(&myPort)) != NULL) {
/* check if we deal with this or not */
if ((item=(void *)match_item(msg->Class, msg->Code))!=NULL) {
ReplyMsg(msg); /* always reply */
run_item(item); /* run the indicated program */
} else {
PutMsg(&myPort, msg); /* pass on to original destination */
}
}
}
}